import random
import time

import numpy as np
from ortools.sat.python import cp_model


def generate_data(job_num, op_num_low, op_num_high):
    """
    该函数用于生成数据，输入输出参数解释如下
    :param job_num: 任务的数量
    :param op_num_low: 生成子任务数量的下限
    :param op_num_high: 生成子任务数量的上限
    :return: data_end:EMS任务的具体信息，即货物数量，该项包含n个任务和各个任务对应的子任务的货物数量
    job_type:货物形态
    data_end_se:自制任务的具体信息，即货物数量，该项包含n个任务和各个任务对应的子任务的货物数量
    d_list:EMS任务的截止时间
    d_list_se:自制任务的截止时间
    data_start_se:各个自制任务的开始时间
    data_end_start:各个EMS任务的开始时间
    """
    due_data = [18 * 60, 21 * 60, 24 * 60]
    start_se = [8 * 60, 9 * 60, 10 * 60, 11 * 60, 13 * 60, 15 * 60]
    # due_data_se = []
    d = []
    data_end = []
    data_end_start = []
    data_end_se = []
    data_start_se = []
    # due_data = []
    job_type = []
    job_p = []
    se = []
    d_list = []
    d_list_se = []
    n = np.random.randint(job_num // 2 + 1, job_num)

    for i in range(job_num):
        job_list = []
        op_type = []
        data_end_start.append(480)
        # d_list.append(random.sample(due_data, 1)[0])
        op_num = np.random.randint(op_num_low, op_num_high)

        if i <= n:
            for j in range(op_num):
                # num = np.random.randint(num_low, num_high)
                ty = np.random.randint(0, 3)
                if ty == 0:
                    num = np.random.randint(40, 250)
                elif ty == 1:
                    num = np.random.randint(200, 800)
                elif ty == 2:
                    num = np.random.randint(200, 800)
                # s = np.random.randint(0, 2)
                op_type.append(ty)
                job_list.append(num)  # d_list.append(random.sample(due_data, 1))
            data_end.append(job_list)
            d_list.append(random.sample(due_data, 1)[0])
            # d.append(d_list)
            job_type.append(op_type)  # job_p.append(i)
        else:
            for j in range(op_num):
                # num = np.random.randint(num_low, num_high)
                ty = np.random.randint(0, 3)
                if ty == 0:
                    num = np.random.randint(40, 250)
                elif ty == 1:
                    num = np.random.randint(200, 800)
                elif ty == 2:
                    num = np.random.randint(200, 800)
                # s = np.random.randint(0, 2)
                # op_type.append(ty)
                job_list.append(num)  # d_list.append(random.sample(due_data, 1))
            data_end_se.append(job_list)
            d_list_se.append(random.sample(due_data, 1)[0])
            data_start_se.append(
                random.sample(start_se, 1)[0])  # d.append(d_list)  # job_type.append(op_type)  # job_p.append(i)

    return data_end, data_end_se, job_type, d_list, d_list_se, data_start_se, data_end_start


def se_solve(job_data_se, d_list_se, data_start_se, V_j, t):
    '''
    该函数用于求解自制任务
    :param job_data_se: 自制任务的具体信息，即货物数量，该项包含n个任务和各个任务对应的子任务的货物数量
    :param d_list_se: 各个自制货物的截止日期
    :param data_start_se: 各个自制任务对应的开始时间
    :param V_j: 不同类型货物对应通道的速度，数量/分钟，0的位置对应栈板，1的位置对应件箱，2的位置对应自制
    :param t: 求解时间，若最后无解，则需调大时间
    :return:solution_x_total 所有子任务的开始处理时间和处理结束时间，单位为分钟
    solution_bool_sub_job 该项对应某一个子任务是否被处理，若为1则被处理，若为0则没被处理
    solution_bool_C 该项对应子任务的通道使用情况，其中为1则该通道被使用，为0则没被使用
    '''
    # V_j = [2, 17, 3]
    t_t_list = [i * 2 * 60 for i in range(5, 12)]
    total_C_list = []
    total_C_se_list = []
    bool_job_list = []
    bool_job_se_list = []
    bool_sub_job_list = []
    bool_sub_job_se_list = []
    job_p_list = []
    job_p_se_list = []
    x_intervals = []
    y_intervals = []
    solution_x_total = []
    solution_bool_sub_job = []
    solution_bool_C = []
    de = []
    total_b = 0
    total_bb = 0
    model = cp_model.CpModel()
    max_time = cp_model.INT32_MAX

    for i in range(len(job_data_se)):
        j_b_se = model.NewBoolVar('%d' % i)
        total_bb += j_b_se
        bool_job_se_list.append(j_b_se)
        job_p_se_sub = []
        C_se_list = []
        bool_sub_job_se = []
        for j in range(len(job_data_se[i])):
            j_sub_b_se = model.NewBoolVar('%d_%d' % (i, j))
            bool_sub_job_se.append(j_sub_b_se)
            total_b += j_sub_b_se
            sub_c_se_list = []
            sub_p_se_list = []
            j_sub_p_se_s = model.NewIntVar(data_start_se[i], 1320, 'p_s_%d_%d' % (i, j))
            j_sub_p_se_e = model.NewIntVar(data_start_se[i], 1320, 'p_e_%d_%d' % (i, j))
            j_sub_p_e_se_1 = model.NewIntVar(data_start_se[i], 1320, 'p_e1_%d_%d' % (i, j))
            due_data_se_d = model.NewBoolVar('due_data_d')
            c_se_d = model.NewBoolVar('c_d')
            model.Add(j_sub_p_se_e <= d_list_se[i]).OnlyEnforceIf(due_data_se_d)
            model.Add(j_sub_p_se_e > d_list_se[i]).OnlyEnforceIf(due_data_se_d.Not())
            sub_p_se_list.append(j_sub_p_se_s)
            sub_p_se_list.append(j_sub_p_se_e)
            sub_p_se_list.append(j_sub_p_e_se_1)
            job_p_se_sub.append(sub_p_se_list)
            b = model.NewBoolVar('%d_%d_%d' % (i, j, 8))
            sub_c_se_list.append(b)

            model.Add(sum(sub_c_se_list) > 0).OnlyEnforceIf(c_se_d)
            model.Add(sum(sub_c_se_list) == 0).OnlyEnforceIf(c_se_d.Not())
            model.Add(due_data_se_d == 1).OnlyEnforceIf(c_se_d)
            model.Add(c_se_d + due_data_se_d == 2).OnlyEnforceIf(j_sub_b_se)
            model.Add(c_se_d + due_data_se_d < 2).OnlyEnforceIf(j_sub_b_se.Not())
            C_se_list.append(sub_c_se_list)
        model.Add(sum(bool_sub_job_se) == len(bool_sub_job_se)).OnlyEnforceIf(j_b_se)
        model.Add(sum(bool_sub_job_se) < len(bool_sub_job_se)).OnlyEnforceIf(j_b_se.Not())
        total_C_se_list.append(C_se_list)
        bool_sub_job_se_list.append(bool_sub_job_se)
        job_p_se_list.append(job_p_se_sub)

    for x in range(len(t_t_list)):
        x_s = model.NewConstant(int(t_t_list[x] - 48))
        ii = model.NewConstant(48)
        x_e = model.NewConstant(t_t_list[x])
        y_s = model.NewConstant(0)
        iii = model.NewConstant(8)
        y_e = model.NewConstant(8)
        x_ii = model.NewOptionalIntervalVar(x_s, ii, x_e, 1, 'x_ii%d' % x)
        y_ii = model.NewOptionalIntervalVar(y_s, iii, y_e, 1, 'y_ii%d' % x)
        x_intervals.append(x_ii)
        y_intervals.append(y_ii)

    for i in range(len(job_data_se)):
        total_interval_se = 0
        x_t_intervals_se = []
        for j in range(len(job_data_se[i])):
            for k in range(len(total_C_se_list[i][j])):
                total_interval_se += total_C_se_list[i][j][k] * V_j[2]
            t_ii = model.NewIntVar(1, 999999, 't_ii_%d' % j)
            model.Add(t_ii == total_interval_se + 1)
            I_se = model.NewIntVar(0, 999999, 'In_%d' % j)
            model.AddDivisionEquality(I_se, job_data_se[i][j], t_ii)
            j_sub_p_I_se_intervals = model.NewOptionalIntervalVar(job_p_se_list[i][j][0], I_se + 30,
                                                                  job_p_se_list[i][j][2], bool_sub_job_se_list[i][j],
                                                                  '%d_%d_I' % (i, j))
            x_t_intervals_se.append(j_sub_p_I_se_intervals)
            # de.append(int(3))
            y_end = model.NewIntVar(0, 10, 'y_end_%d%d%d' % (i, j, 8))
            j_sub_p_se_intervals = model.NewOptionalIntervalVar(job_p_se_list[i][j][0], I_se + 1,
                                                                job_p_se_list[i][j][1], total_C_se_list[i][j][0],
                                                                'p_%d_%d' % (i, j))
            j_sub_c_se_intervals = model.NewOptionalIntervalVar(7, 1, y_end, total_C_se_list[i][j][0],
                                                                'c_%d_%d' % (i, j))
            x_intervals.append(j_sub_p_se_intervals)
            y_intervals.append(j_sub_c_se_intervals)

        model.AddNoOverlap(x_t_intervals_se)
    model.AddNoOverlap2D(x_intervals, y_intervals)

    model.Maximize(total_bb)
    solver = cp_model.CpSolver()
    solver.parameters.num_search_workers = 8
    solver.parameters.max_time_in_seconds = t
    # solver.parameters.log_search_progress = True
    status = solver.Solve(model)

    if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
        print("status: ", status)

        for i in range(len(job_data_se)):
            solu_x_sub_se = []
            for j in range(len(job_data_se[i])):
                solution_x_se = []
                solution_x_se.append(solver.Value(job_p_se_list[i][j][0]))
                solution_x_se.append(solver.Value(job_p_se_list[i][j][1]))
                solu_x_sub_se.append(solution_x_se)
            solution_x_total.append(solu_x_sub_se)

        for i in range(len(job_data_se)):
            solu_bool_sub_se = []
            for j in range(len(job_data_se[i])):
                solu_bool_sub_se.append(solver.Value(bool_sub_job_se_list[i][j]))
            solution_bool_sub_job.append(solu_bool_sub_se)

        for i in range(len(job_data_se)):
            solu_C_se_sub = []
            for j in range(len(job_data_se[i])):
                solu_C_sub_sub_se = []
                for k in range(len(total_C_se_list[i][j])):
                    solu_C_sub_sub_se.append(solver.Value(total_C_se_list[i][j][k]))
                solu_C_se_sub.append(solu_C_sub_sub_se)
            solution_bool_C.append(solu_C_se_sub)

        print("youjie")
    else:
        print('No solution found.')

    return solution_x_total, solution_bool_sub_job, solution_bool_C


def solve(job_data, d_list, job_type, data_end_start, sxt, sbsj, sbc, V_j, t):
    """
    该函数用于求解时间窗，输入输出参数解释如下
    :param job_data:EMS任务的具体信息，即货物数量，该项包含n个任务和各个任务对应的子任务的货物数量,同时任务的优先级默认从高到低依次排列
    :param d_list:EMS货物的截止日期
    :param job_type:EMS货物形态 0可代表栈板，1代表件箱，2代表gtp
    :param data_end_start:各个任务对应的开始时间
    :param sxt:所有自制子任务的开始处理时间和处理结束时间，单位为分钟
    :param sbsj:该项对应某一个自制子任务是否被处理，若为1则被处理，若为0则没被处理
    :param sbc:该项对应自制子任务的通道使用情况，其中为1则该通道被使用，为0则没被使用
    :param V_j: 不同类型货物对应通道的速度，数量/分钟，0的位置对应栈板，1的位置对应件箱，2的位置对应自制
    :param t:求解时间，若最后无解，则需调大时间
    :return: solution_x_total 所有子任务的开始处理时间和处理结束时间，单位为分钟
    solution_bool_sub_job 该项对应某一个子任务是否被处理，若为1则被处理，若为0则没被处理
    solution_bool_C 该项对应子任务的通道使用情况，其中为1则该通道被使用，为0则没被使用
    """

    # V_j = [2, 17, 3]
    t_t_list = [i * 2 * 60 for i in range(5, 12)]
    total_C_list = []
    total_C_se_list = []
    bool_job_list = []
    bool_job_se_list = []
    bool_sub_job_list = []
    bool_sub_job_se_list = []
    job_p_list = []
    job_p_se_list = []
    x_intervals = []
    y_intervals = []
    solution_x_total = []
    solution_bool_sub_job = []
    solution_bool_C = []
    de = []
    rs_c = []
    total_b = 0
    total_bb = 0

    model = cp_model.CpModel()
    max_time = cp_model.INT32_MAX
    print("job_data: ", job_data)
    # print("d: ", d)

    for i in range(len(job_data)):
        ts = data_end_start[i]
        j_b = model.NewBoolVar('%d' % i)
        total_bb += j_b
        bool_job_list.append(j_b)
        job_p_sub = []
        C_list = []
        bool_sub_job = []
        for j in range(len(job_data[i])):
            j_sub_b = model.NewBoolVar('%d_%d' % (i, j))
            bool_sub_job.append(j_sub_b)
            total_b += j_sub_b
            sub_c_list = []
            sub_p_list = []
            j_sub_p_s = model.NewIntVar(ts, 1320, 'p_s_%d_%d' % (i, j))
            j_sub_p_e = model.NewIntVar(ts, 1320, 'p_e_%d_%d' % (i, j))
            j_sub_p_e_1 = model.NewIntVar(ts, 1320, 'p_e1_%d_%d' % (i, j))
            due_data_d = model.NewBoolVar('due_data_d')
            c_d = model.NewBoolVar('c_d')
            model.Add(j_sub_p_e <= d_list[i]).OnlyEnforceIf(due_data_d)
            model.Add(j_sub_p_e > d_list[i]).OnlyEnforceIf(due_data_d.Not())
            sub_p_list.append(j_sub_p_s)
            sub_p_list.append(j_sub_p_e)
            sub_p_list.append(j_sub_p_e_1)
            job_p_sub.append(sub_p_list)
            if job_type[i][j] == 0:
                b = model.NewBoolVar('%d_%d_%d' % (i, j, 7))
                sub_c_list.append(b)
            else:
                for m in range(6):
                    b = model.NewBoolVar('%d_%d_%d' % (i, j, m))
                    sub_c_list.append(b)

            model.Add(sum(sub_c_list) > 0).OnlyEnforceIf(c_d)
            model.Add(sum(sub_c_list) == 0).OnlyEnforceIf(c_d.Not())
            model.Add(due_data_d == 1).OnlyEnforceIf(c_d)
            model.Add(c_d + due_data_d == 2).OnlyEnforceIf(j_sub_b)
            model.Add(c_d + due_data_d < 2).OnlyEnforceIf(j_sub_b.Not())
            C_list.append(sub_c_list)
        model.Add(sum(bool_sub_job) == len(bool_sub_job)).OnlyEnforceIf(j_b)
        model.Add(sum(bool_sub_job) < len(bool_sub_job)).OnlyEnforceIf(j_b.Not())
        total_C_list.append(C_list)
        bool_sub_job_list.append(bool_sub_job)
        job_p_list.append(job_p_sub)

    for x in range(len(t_t_list)):
        x_s = model.NewConstant(int(t_t_list[x] - 48))
        ii = model.NewConstant(48)
        x_e = model.NewConstant(t_t_list[x])
        y_s = model.NewConstant(0)
        iii = model.NewConstant(7)
        y_e = model.NewConstant(7)
        x_ii = model.NewOptionalIntervalVar(x_s, ii, x_e, 1, 'x_ii%d' % x)
        y_ii = model.NewOptionalIntervalVar(y_s, iii, y_e, 1, 'y_ii%d' % x)
        x_intervals.append(x_ii)
        y_intervals.append(y_ii)

    for g in range(len(sxt)):
        for i in range(len(sxt[g])):
            x_s = model.NewConstant(sxt[g][i][0])
            ii = model.NewConstant(sxt[g][i][1] - sxt[g][i][0])
            x_e = model.NewConstant(sxt[g][i][1])
            y_s = model.NewConstant(7)
            iii = model.NewConstant(1)
            y_e = model.NewConstant(8)
            # print("sbsj[g][i]: ", sbsj[g][i])
            if sbsj[g][i] == 1:
                x_ii = model.NewOptionalIntervalVar(x_s, ii, x_e, sbsj[g][i], 'x_ii%d' % i)
                y_ii = model.NewOptionalIntervalVar(y_s, iii, y_e, sbsj[g][i], 'y_ii%d' % i)
                x_intervals.append(x_ii)
                y_intervals.append(y_ii)
                de.append(int(3))
                rs_c.append(x_ii)

    for i in range(len(job_data)):
        total_interval = 0
        x_t_intervals = []
        for j in range(len(job_data[i])):
            for k in range(len(total_C_list[i][j])):
                total_interval += total_C_list[i][j][k] * V_j[job_type[i][j]]
            t_i = model.NewIntVar(1, 999999, 't_i_%d' % j)
            model.Add(t_i == total_interval + 1)
            I = model.NewIntVar(0, 999999, 'In_%d' % j)
            model.AddDivisionEquality(I, job_data[i][j], t_i)
            j_sub_p_I_intervals = model.NewOptionalIntervalVar(job_p_list[i][j][0], I + 30, job_p_list[i][j][2],
                                                               bool_sub_job_list[i][j], '%d_%d_I' % (i, j))
            x_t_intervals.append(j_sub_p_I_intervals)
            for m in range(len(total_C_list[i][j])):
                # de.append(int(17))
                y_end = model.NewIntVar(1, 6, 'y_end_%d%d%d' % (i, j, m))
                j_sub_p_intervals = model.NewOptionalIntervalVar(job_p_list[i][j][0], I + 1, job_p_list[i][j][1],
                                                                 total_C_list[i][j][m], 'p_%d_%d' % (i, j))
                j_sub_c_intervals = model.NewOptionalIntervalVar(m, 1, y_end, total_C_list[i][j][m], 'c_%d_%d' % (i, j))
                if job_type[i][j] == 1:
                    rs_c.append(j_sub_p_intervals)
                    de.append(int(17))
                x_intervals.append(j_sub_p_intervals)
                y_intervals.append(j_sub_c_intervals)

        model.AddNoOverlap(x_t_intervals)

    model.AddNoOverlap2D(x_intervals, y_intervals)
    model.AddCumulative(rs_c, de, 84)

    for i in range(len(job_data) - 1):
        model.Add(bool_job_list[i] == 1).OnlyEnforceIf(bool_job_list[i + 1])

    model.Maximize(total_bb)
    solver = cp_model.CpSolver()
    solver.parameters.num_search_workers = 8
    solver.parameters.max_time_in_seconds = t
    # solver.parameters.log_search_progress = True
    status = solver.Solve(model)

    if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
        print("status: ", status)
        for i in range(len(job_data)):
            solu_x_sub = []
            for j in range(len(job_data[i])):
                solution_x = []
                solution_x.append(solver.Value(job_p_list[i][j][0]))
                solution_x.append(solver.Value(job_p_list[i][j][1]))
                solu_x_sub.append(solution_x)
            solution_x_total.append(solu_x_sub)

        solution_x_total = solution_x_total + sxt

        for i in range(len(job_data)):
            solu_bool_sub = []
            for j in range(len(job_data[i])):
                solu_bool_sub.append(solver.Value(bool_sub_job_list[i][j]))
            solution_bool_sub_job.append(solu_bool_sub)

        solution_bool_sub_job = solution_bool_sub_job + sbsj

        for i in range(len(job_data)):
            solu_C_sub = []
            for j in range(len(job_data[i])):
                solu_C_sub_sub = []
                for k in range(len(total_C_list[i][j])):
                    solu_C_sub_sub.append(solver.Value(total_C_list[i][j][k]))
                solu_C_sub.append(solu_C_sub_sub)
            solution_bool_C.append(solu_C_sub)

        solution_bool_C = solution_bool_C + sbc

        print("youjie")
    else:
        print('No solution found.')

    return solution_x_total, solution_bool_sub_job, solution_bool_C


def get_end_time(solution_x_total, solution_bool_sub_job):
    '''
    该函数用于得到加入休息时间后最终的时间窗结果
    :param solution_x_total: 所有子任务的开始处理时间和处理结束时间，单位为分钟
    :param solution_bool_sub_job: 该项对应某一个子任务是否被处理，若为1则被处理，若为0则没被处理
    :return: solution_x_total：最终所有子任务的开始处理时间和处理结束时间，单位为分钟
    '''
    # 720 1020
    for i in range(len(solution_x_total)):
        for j in range(len(solution_x_total[i])):
            if solution_bool_sub_job[i][j] == 1:
                if solution_x_total[i][j][0] < 720 and solution_x_total[i][j][1] > 720 and solution_x_total[i][j][
                    1] <= 1020:
                    solution_x_total[i][j][1] += 60

                elif solution_x_total[i][j][0] >= 720 and solution_x_total[i][j][1] <= 1020:
                    solution_x_total[i][j][0] += 60
                    solution_x_total[i][j][1] += 60

                elif solution_x_total[i][j][0] < 1020 and solution_x_total[i][j][1] > 1020:
                    solution_x_total[i][j][0] += 60
                    solution_x_total[i][j][1] += 120

                elif solution_x_total[i][j][0] >= 1020 and solution_x_total[i][j][1] > 1020:
                    solution_x_total[i][j][0] += 120
                    solution_x_total[i][j][1] += 120

                elif solution_x_total[i][j][0] < 720 and solution_x_total[i][j][1] >= 1020:
                    solution_x_total[i][j][1] += 120

    return solution_x_total


def plot_graph(job_data, job_data_se, solution_x_total, solution_bool_sub_job, solution_bool_C):
    '''
    该函数用于可视化
    '''
    import matplotlib.pyplot as plt

    colors = []
    for i in range(len(job_data) + len(job_data_se)):
        colors.append(f'#%06x' % random.randint(0, 0xFFFFFF))

    fig, ax = plt.subplots()

    for i in range(len(solution_bool_C)):
        if i < len(job_data):
            for j in range(len(solution_bool_C[i])):
                for k in range(len(solution_bool_C[i][j])):
                    color = colors[i]
                    if solution_bool_sub_job[i][j] and solution_bool_C[i][j][k]:
                        if len(solution_bool_C[i][j]) == 1:
                            rectangle = plt.Rectangle((solution_x_total[i][j][0] / 60, 6),
                                                      (solution_x_total[i][j][1] - solution_x_total[i][j][0]) / 60, 1,
                                                      facecolor=color)
                            rectangle.set_edgecolor('black')
                            rectangle.set_linewidth(1.5)
                            ax.add_patch(rectangle)
                        else:
                            rectangle = plt.Rectangle((solution_x_total[i][j][0] / 60, k),
                                                      (solution_x_total[i][j][1] - solution_x_total[i][j][0]) / 60, 1,
                                                      facecolor=color)
                            rectangle.set_edgecolor('black')
                            rectangle.set_linewidth(1.5)
                            ax.add_patch(rectangle)

        else:
            for j in range(len(solution_bool_C[i])):
                for k in range(len(solution_bool_C[i][j])):
                    color = colors[i]
                    if solution_bool_sub_job[i][j] and solution_bool_C[i][j][k]:
                        rectangle = plt.Rectangle((solution_x_total[i][j][0] / 60, 7),
                                                  (solution_x_total[i][j][1] - solution_x_total[i][j][0]) / 60, 1,
                                                  facecolor=color)
                        rectangle.set_edgecolor('black')
                        rectangle.set_linewidth(1.5)
                        ax.add_patch(rectangle)

    for x in [i * 2 for i in range(1, 13)]:
        ax.axvline(x, color='red', linestyle='--', linewidth=1)

    ax.axvline(13, color='red', linestyle='--', linewidth=1)

    ax.axvline(19, color='red', linestyle='--', linewidth=1)

    ax.set_xlim(0, 25)
    ax.set_ylim(0, 10)

    ax.set_xlabel('Time (hours)')
    ax.set_ylabel('channel')
    ax.set_title('Time window')

    plt.show()


if __name__ == '__main__':
    t1 = time.time()
    V_j = [2, 17, 3]
    data_end, data_end_se, job_type, d_list, d_list_se, data_start_se, data_end_start = generate_data(30, 4, 8)
    print("data_end: ", data_end)
    print("data_end_se: ", data_end_se)
    print("job_type: ", job_type)
    print("d_list: ", d_list)
    print("d_list_se: ", d_list_se)
    print("data_start_se: ", data_start_se)
    sxt, sbsj, sbc = se_solve(data_end_se, d_list_se, data_start_se, V_j, 60.0)
    print("sxt: ", sxt)
    print("sbsj: ", sbsj)
    print("sbc: ", sbc)
    solution_x_total, solution_bool_sub_job, solution_bool_C = solve(data_end, d_list, job_type, data_end_start, sxt,
                                                                     sbsj, sbc, V_j, 60.0)
    print("solution_x_total: ", solution_x_total)
    print("solution_bool_sub_job: ", solution_bool_sub_job)
    print("solution_bool_C: ", solution_bool_C)
    t2 = time.time()
    print("t: ", t2 - t1)
    solution_x_total = get_end_time(solution_x_total, solution_bool_sub_job)
    print("solution_x_total: ", solution_x_total)
    plot_graph(data_end, data_end_se, solution_x_total, solution_bool_sub_job, solution_bool_C)
